package com.wzdigit.wms.wms.service.core.transfer;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.base.Preconditions;
import com.wzdigit.framework.Shift;
import com.wzdigit.mes.basic.api.BasicDataItemDetailApi;
import com.wzdigit.mes.basic.api.BasicSimpleCodeRuleApi;
import com.wzdigit.mes.basic.dto.DataItemDetailDTO;
import com.wzdigit.wms.basic.client.Pager;
import com.wzdigit.wms.basic.client.PagerInfo;
import com.wzdigit.wms.basic.client.request.asn.SrarchTransferWareHouseRequest;
import com.wzdigit.wms.basic.client.request.asn.UpdateAsnHeaderRequest;
import com.wzdigit.wms.basic.client.request.transfer.WhsReq;
import com.wzdigit.wms.basic.client.response.Result;
import com.wzdigit.wms.basic.client.response.asnHeader.TransferWareHouseDtlExt;
import com.wzdigit.wms.basic.client.response.asnHeader.TransferWareHouseExt;
import com.wzdigit.wms.basic.client.response.report.TransferGoodsExt;
import com.wzdigit.wms.basic.domain.basic.Warehouse;
import com.wzdigit.wms.basic.domain.dtos.inventory.UpdateInventoryInputDto;
import com.wzdigit.wms.basic.domain.dtos.transfer.TransferDtlDto;
import com.wzdigit.wms.basic.domain.dtos.transfer.TransferDto;
import com.wzdigit.wms.basic.domain.inventory.Goods;
import com.wzdigit.wms.basic.domain.inventory.GoodsLog;
import com.wzdigit.wms.basic.domain.inventory.InvTrans;
import com.wzdigit.wms.basic.domain.transfer.TransferDtl;
import com.wzdigit.wms.basic.domain.transfer.TransferDtlGoods;
import com.wzdigit.wms.basic.domain.transfer.TransferHeader;
import com.wzdigit.wms.basic.enums.*;
import com.wzdigit.wms.basic.enums.basic.LotAttrDtlEnum;
import com.wzdigit.wms.basic.mapper.core.transfer.TransferDtlGoodsMapper;
import com.wzdigit.wms.basic.mapper.core.transfer.TransferDtlMapper;
import com.wzdigit.wms.basic.mapper.core.transfer.TransferHeaderMapper;
import com.wzdigit.wms.basic.util.DateUtils;
import com.wzdigit.wms.common.entity.ExcelExportConfig;
import com.wzdigit.wms.common.utils.HttpExcel;
import com.wzdigit.wms.basic.util.HttpSessionUtil;
import com.wzdigit.wms.basic.util.common.FileUrlString;
import com.wzdigit.wms.common.entity.StatusCode;
import com.wzdigit.wms.wms.service.basic.FileService;
import com.wzdigit.wms.wms.service.basic.WarehouseService;
import com.wzdigit.wms.wms.service.core.GoodsService;
import com.wzdigit.wms.wms.service.core.InvLocService;
import com.wzdigit.wms.basic.service.code.InventoryService;
import com.wzdigit.wms.wms.service.order.TurnWarehouseService;
import lombok.extern.slf4j.Slf4j;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.export.ooxml.JRXlsxExporter;
import net.sf.jasperreports.engine.util.JRLoader;
import net.sf.jasperreports.export.*;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.sql.Connection;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 库存调拨单表头 服务类
 * </p>
 *
 * @author
 * @since 2021-01-19
 */
@Service
@Slf4j
public class TransferHeaderService {

    @Autowired
    private TransferHeaderMapper transferHeaderMapper;
    
    @Autowired
	private TransferDtlGoodsMapper transferDtlGoodsMapper;
    
    @Autowired
    private TransferDtlMapper transferDtlMapper;

    @Autowired
    @Lazy
    private WarehouseService warehouseService;

    @Autowired
    private TurnWarehouseService turnWarehouseService;

    @Autowired
    private TransferDtlGoodsService transferDtlGoodsService;

    @Autowired
    @Lazy
    private InvLocService invLocService;
    
    @Autowired
	private InventoryService inventoryService;
	
	@Autowired
	private GoodsService goodsService;
	
	@Autowired
	private DataSource dataSource;
	
    //普通调拨(一步调拨)
    @Value("${order_type.transfer.ptyb}")
    private String ptyb;

    @Reference(version = "${dubbo.consumers.basic.data.item.detail.api:1.0.0}", check = false)
    private BasicDataItemDetailApi basicDataItemDetailApi;
    
    @Reference(version = "${dubbo.consumers.basic.simple.code.rule.api:1.0.0}", check = false)
    private BasicSimpleCodeRuleApi basicSimpleCodeRuleApi;
    
    @Value("${order_type.transfer.dictionary_code}")
    private String dictionaryCode;

    @Autowired
	private FileService fileService;

    private static final String RETURN = "Return";
    private static final String PONO_CODE = LotAttrDtlEnum.PO_NO.code;
    
    private static Map<Integer, String> transferHeaderStatusMap = TransferHeaderStatusEnum.getEnumByDescription();
    private static Map<Integer, String> printFlagMap = PrintFlagEnum.getEnumByDescription();

    /**
     * 根据实体新增一条记录
     *
     * @param transferHeader
     * @return
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public TransferHeader addNewOne(TransferHeader transferHeader) {
        int row = transferHeaderMapper.insert(transferHeader);
        log.info("成功新增{}条记录", row);

        return transferHeader;
    }

    /**
     * 根据实体更新一条记录
     *
     * @param transferHeader
     * @return
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public TransferHeader updateOne(TransferHeader transferHeader) {
        int row = transferHeaderMapper.updateById(transferHeader);
        log.info("成功更新{}条记录", row);

        return transferHeader;
    }
    
    /**
     * 根据转仓单号查找
     * 
     * @param transferNo
     * @return
     */
    public TransferHeader getByTransferNo(String transferNo) {
        //创建类型的条件构造器
        QueryWrapper<TransferHeader> wrapper = new QueryWrapper<>();
        wrapper.eq("TRANSFER_NO", transferNo);

        TransferHeader transferHeader = transferHeaderMapper.selectOne(wrapper);
        return transferHeader;
    }
    
    /**
     * 根据主键查询
     * @param transferHeaderId
     * @return
     */
    public TransferHeader getByHeaderId(Integer transferHeaderId) {
        TransferHeader transferHeader = transferHeaderMapper.selectById(transferHeaderId);
        return transferHeader;
    }

    /**
     * 获取所有符合当前登录用户权限的仓库转仓单
     * @param search
     * @param pager
     * @param servletRequest
     * @return
     */
    public PagerInfo<List<TransferWareHouseExt>> searchTransferWareHouse(
    		SrarchTransferWareHouseRequest search, Pager<?> pager, 
    		HttpServletRequest servletRequest) {
        //查询当前用户权限仓库
        List<Integer> whsIdList = warehouseService.getWareHouseIds(servletRequest);
        
        search.setWareHouseIds(whsIdList);
        if (search.getStartTime() != null) {
            search.setStartDate(DateUtils.getStartTime(search.getStartTime()));
        }
        if (search.getEndTime() != null) {
            search.setEndDate(DateUtils.getEndTime(search.getEndTime()));
        }
        /*if (StringUtils.isNotBlank(search.getPoNo())) {
        	search.setPoNo("\"" + PONO_CODE + "\":\"" + search.getPoNo() + "\"");
        }*/

		Page<?> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
        PagerInfo<List<TransferWareHouseExt>> pagerInfo = new PagerInfo<List<TransferWareHouseExt>>();
        
        List<TransferWareHouseExt> list = transferHeaderMapper.getListTable(search);
		for (TransferWareHouseExt ext : list) {
			if (ext.getTransferType()!=null){
				TransferTypeEnum typeEnum = TransferTypeEnum.getEnumByCode(ext.getTransferType());
				if (typeEnum!=null){
					ext.setTransferTypeStr(typeEnum.getEnumName());
				}
			}
		}
        
        pagerInfo.setTotalCount(page.getTotal());
        pagerInfo.setItems(list);
        
        return pagerInfo;
    }

    /**
     * 查看转仓单明细
     * @param pager
     * @return
     */
	public PagerInfo<List<TransferWareHouseDtlExt>> searchTransferWareHouseDtl(Integer transferHeaderId, Pager<?> pager) {
		Page<?> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
		PagerInfo<List<TransferWareHouseDtlExt>> pagerInfo = new PagerInfo<List<TransferWareHouseDtlExt>>();

		List<TransferWareHouseDtlExt> datas = transferDtlMapper.getListDtlTable(transferHeaderId);
		datas = datas.stream().sorted(Comparator.comparing(TransferWareHouseDtlExt::getIsTop).reversed())
				.collect(Collectors.toList());
		datas.forEach(one -> {
            if (StringUtils.isNotBlank(one.getLotAttrCode()) && one.getPoNo() == null) {
                Map<String, String> map = JSON.parseObject(one.getLotAttrCode(), Map.class);
                one.setPoNo(map.get(PONO_CODE));
            }
        });

		pagerInfo.setTotalCount(page.getTotal());
        pagerInfo.setItems(datas);
		return pagerInfo;
	}


    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Result<Boolean> close(List<Integer> transferHeaderIds, HttpServletRequest servletRequest) throws Exception {
        Preconditions.checkNotNull(transferHeaderIds);
        String userName = HttpSessionUtil.getLoginName(servletRequest);
        Date date = new Date();
        for (Integer transferHeaderId : transferHeaderIds) {
        	// 调拨单头
            TransferHeader transferHeader = transferHeaderMapper.selectById(transferHeaderId);
            if (transferHeader.getStatus() != TransferHeaderStatusEnum.DOING.getCode() &&
            		transferHeader.getStatus() != TransferHeaderStatusEnum.CREATE.getCode()) {
            	// 只处理进行中的或者新建
                Shift.fatal(StatusCode.SERVER_ASNHEADERNOCLOSE_ERROR);
            }
            
            // 调拨单明细【进行中的】
            QueryWrapper<TransferDtl> transferDtlQueryWrapper = new QueryWrapper<TransferDtl>();
            transferDtlQueryWrapper.eq("TRANSFER_HEADER_ID", transferHeaderId);
            transferDtlQueryWrapper.and(wrapper -> {
    			wrapper.eq("STATUS", TransferDtlStatusEnum.CREATE.code)
    			.or().eq("STATUS", TransferDtlStatusEnum.DOING.code);});
            List<TransferDtl> transferDtls = transferDtlMapper.selectList(transferDtlQueryWrapper);
            for (TransferDtl transferDtl : transferDtls) {
            	// 有效的转仓单货品清单集合【待接收】
    			QueryWrapper<TransferDtlGoods> transferDtlGoodsWrapper = new QueryWrapper<>();
    			transferDtlGoodsWrapper.eq("TRANSFER_DTL_ID", transferDtl.getTransferDtlId());
    			transferDtlGoodsWrapper.eq("STATUS", TransferDtlGoodStatusEnum.WAIT_RECEIVE.code);	// 待接收
    			List<TransferDtlGoods> dtlGoodsList = transferDtlGoodsMapper.selectList(transferDtlGoodsWrapper);
    			
    			inventory(transferHeader, transferDtl, dtlGoodsList, userName, date);
    			
            	// 更新转仓单明细【实收数=转仓数、状态=关闭】
    			transferDtl.setTransitQty(0);		// 在途数量
				transferDtl.setModifyTime(date);
				transferDtl.setModifyUser(userName);
				transferDtl.setStatus(TransferDtlStatusEnum.CLOSE.code); 	// 关闭
				transferDtlMapper.updateById(transferDtl);
            }
            
            // 更新转仓单表头【状态=关闭】
            transferHeader.setModifyTime(date);
            transferHeader.setModifyUser(userName);
            transferHeader.setStatus(TransferHeaderStatusEnum.CLOSE.getCode());
            transferHeaderMapper.updateById(transferHeader);
        }
        return new Result<Boolean>(true, "关闭成功！");
    }


    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public Result<Boolean> update(UpdateAsnHeaderRequest request, String userName) throws Exception {
		Preconditions.checkNotNull(request);
		// 获取收货单主档数据
		TransferHeader transferHeader = transferHeaderMapper.selectById(request.getTransferHeaderId());

		// 只有【新建】状态允许修改操作
		if (!TransferHeaderStatusEnum.CREATE.getCode().equals(transferHeader.getStatus())) {
			Shift.fatal(StatusCode.SERVER_ASNHEADERNOEDIT_ERROR);
		}

		// TODO 修改目的仓后，对应库存相关信息也要修改

		// TODO 原【目的仓】预收减少

		// TODO 现【目的仓】预收增加，可能不存在

		// TODO 写日志，源-》目的

		/*Integer fmWhs = transferHeader.getFmWhs();//源仓ID
		Warehouse warehouseSource = warehouseService.selectByPK(originalToWhs);*/
		
		// 源仓
		Warehouse warehouseSource = warehouseService.selectByPK(transferHeader.getFmWhs());
		WhsReq turnWhsReq = new WhsReq();
		BeanUtils.copyProperties(warehouseSource, turnWhsReq);

		// 原【目的仓】
		Warehouse originalWarehouseTarget = warehouseService.selectByPK(transferHeader.getToWhs());
		WhsReq originalTargetWhsReq = new WhsReq();
		BeanUtils.copyProperties(originalWarehouseTarget, originalTargetWhsReq);

		// 新【目的仓】
		Warehouse warehouseTarget = warehouseService.selectByPK(request.getToWhs());
		WhsReq targetWhsReq = new WhsReq();
		BeanUtils.copyProperties(warehouseTarget, targetWhsReq);

		// 根据数据字典获取调拨单类型
		/*List<DataItemDetailDTO> dataItemDetailDTOList = basicDataItemDetailApi.getDataItemDetailByCode(dictionaryCode);
		List<DataItemDetailDTO> dataItemDetailDTOS = dataItemDetailDTOList.stream()
				.filter(s -> s.getItemName().equals(ptyb)).collect(Collectors.toList());
		DataItemDetailDTO dataItemDetailDTO = dataItemDetailDTOS.get(0);*/
		
		// 调拨单类型
		/*String transferType = dataItemDetailDTO.getItemValue();*/
		
		// 设置调拨单信息,todo
		/*TransferDto transferDto = new TransferDto();
		transferDto.setTransferHeader(transferHeader);
		transferHeader.setToWhs(request.getToWhs());*/
		
		// 创建类型的条件构造器
		/*QueryWrapper<TransferDtl> wrapper = new QueryWrapper<>();
		wrapper.eq("TRANSFER_HEADER_ID", transferHeader.getTransferHeaderId());
		List<TransferDtl> transferDtls = transferDtlMapper.selectList(wrapper);

		List<TransferDtlDto> transferDtlDtoList = new ArrayList<>();

		for (TransferDtl transferDtl : transferDtls) {
			TransferDtlDto transferDtlDto = new TransferDtlDto();
			transferDtlDto.setTransferDtl(transferDtl);

			List<TransferDtlGoods> transferDtlGoodsList = transferDtlGoodsService
					.selectByDtlId(transferDtl.getTransferDtlId());
			transferDtlDto.setTransferDtlGoods(transferDtlGoodsList);

			transferDtlDtoList.add(transferDtlDto);
		}

		transferDto.setTransferDtlDtoList(transferDtlDtoList);*/
		// 设置调拨单信息,todo
		
		/*turnWarehouseService.changeInventory(localDate, userName, turnWhsReq, targetWhsReq, 
				request.getTransNo(),transferDto, transferType, transferDtlDtoList, true);*/
		
		// 原【目的仓】也修改
		/*for (TransferDtlDto transferDtlDto : transferDtlDtoList) {
			TransferDtl transferDtl = transferDtlDto.getTransferDtl();

			Integer orderQty = transferDtl.getOrderQty();// 调拨数量
			Integer fmSku = transferDtl.getFmSku();

			InvLoc invLoc = invLocService.selectByWhsAndSku(request.getToWhs(), fmSku);
			BigDecimal preInQty = invLoc.getPreInQty();// 预收

			BigDecimal bigOrderQty = new BigDecimal(orderQty);// 调拨数量

			preInQty = preInQty.multiply(bigOrderQty);

			invLocService.updateByPkAndInQty(invLoc.getInvLocId(), preInQty);
		}*/

		// TODO 修改目的仓后，对应库存相关信息也要修改

		// todo 先将其送回源仓，再送至目的仓
		Date localDate = new Date();

		// 根据数据字典获取调拨单类型
		List<DataItemDetailDTO> dataItemDetailDTOList = basicDataItemDetailApi.getDataItemDetailByCode(dictionaryCode);
		List<DataItemDetailDTO> dataItemDetailDTOS = dataItemDetailDTOList.stream()
				.filter(s -> s.getItemName().equals(ptyb)).collect(Collectors.toList());
		DataItemDetailDTO dataItemDetailDTO = dataItemDetailDTOS.get(0);
		// 调拨单类型
		String transferType = dataItemDetailDTO.getItemValue();

		// 设置调拨单信息,todo
		TransferDto transferDto = new TransferDto();
		transferDto.setTransferHeader(transferHeader);
		transferHeader.setToWhs(request.getToWhs());

		// 创建类型的条件构造器
		QueryWrapper<TransferDtl> wrapper = new QueryWrapper<>();
		wrapper.eq("TRANSFER_HEADER_ID", transferHeader.getTransferHeaderId());
		List<TransferDtl> transferDtls = transferDtlMapper.selectList(wrapper);

		List<TransferDtlDto> transferDtlDtoList = new ArrayList<>();

		for (TransferDtl transferDtl : transferDtls) {
			TransferDtlDto transferDtlDto = new TransferDtlDto();
			transferDtlDto.setTransferDtl(transferDtl);

			List<TransferDtlGoods> transferDtlGoodsList = transferDtlGoodsService
					.selectByDtlId(transferDtl.getTransferDtlId());
			transferDtlDto.setTransferDtlGoods(transferDtlGoodsList);

			transferDtlDtoList.add(transferDtlDto);
		}

		transferDto.setTransferDtlDtoList(transferDtlDtoList);
		// 将其送回源仓
		turnWarehouseService.changeInventory2(localDate, userName, originalTargetWhsReq, 
				turnWhsReq, transferHeader.getTransferNo(), transferDto, transferType, transferDtlDtoList, true);

		// 将其送至目的仓
		turnWarehouseService.changeInventory(localDate, userName, turnWhsReq, targetWhsReq, 
				transferHeader.getTransferNo(), transferDto, transferType, transferDtlDtoList, false);
		
		transferHeader.setToWhs(request.getToWhs());
		int i = transferHeaderMapper.updateById(transferHeader);

		if (i == 1) {
			return new Result<Boolean>(true, "编辑成功！");
		} else {
			return new Result<Boolean>(false, "编辑失败！");
		}
	}


 	/**
 	 * 关闭转仓单时，更新库存
 	 * @param header
 	 * @param dtl
 	 * @param dtlGoodsList
 	 * @param loginName
 	 * @param localDate
 	 * @throws Exception
 	 */
 	private void inventory(TransferHeader header, TransferDtl dtl, 
 			List<TransferDtlGoods> dtlGoodsList, String loginName, Date localDate) throws Exception {
		int size = dtlGoodsList.size();
		if (size == 0) {
			return;
		}
		BigDecimal returnQty = new BigDecimal(size).negate();
		
 		// 来源仓
 		UpdateInventoryInputDto source = new UpdateInventoryInputDto();
 		source.setOperator(loginName);
 		source.setPreOutQty(returnQty); 	// 预支数量【-】
 		source.setWhsId(header.getFmWhs()); // 来源仓库

 		source.setUnit(dtl.getUnit()); 			// 单位
 		source.setSkuId(dtl.getFmSku()); 		// 物料ID
 		source.setOwner(dtl.getFmOwner()); 		// 货主ID
 		source.setLotNo(dtl.getFmLotno()); 		// 内部批次号
 		source.setFactory(dtl.getFmFactory()); 	// 工厂
 		source.setInvAttr(dtl.getFmInvAttr()); 	// 库存性质
 		source.setVendorId(dtl.getFmVendor()); 	// 供应商ID
 		source.setQaStatus(dtl.getFmQaStatus());// 品质状态

 		// 来源仓日志
 		InvTrans sourceInvTrans = new InvTrans();
 		sourceInvTrans.setOperator(loginName);
 		sourceInvTrans.setCreateTime(localDate);
 		sourceInvTrans.setCreateUser(loginName);
 		
 		sourceInvTrans.setFmUnit(dtl.getUnit()); 				// 单位
 		sourceInvTrans.setFmSkuId(dtl.getFmSku());
 		sourceInvTrans.setFmOwner(dtl.getFmOwner());
 		sourceInvTrans.setDocLineNo(dtl.getTransferLineNo()); 	// 单据行号

 		sourceInvTrans.setFmWhsId(header.getFmWhs());
 		sourceInvTrans.setDocNo(header.getTransferNo());
 		sourceInvTrans.setDocType(header.getTransferType());
 		sourceInvTrans.setTransTime(header.getTransferCreateTime());
 		
 		sourceInvTrans.setOpCode(RETURN);
 		sourceInvTrans.setStatus(InvTransStatusEnum.FINISHED.code);
 		
 		sourceInvTrans.setFmPreOutQty(source.getPreOutQty()); 	// 预支数量
 		inventoryService.inventoryOut(source, sourceInvTrans);

 		// 目的仓
 		UpdateInventoryInputDto target = new UpdateInventoryInputDto();
 		target.setOperator(loginName);
 		target.setPreInQty(returnQty); 		// 预收数量【-】
 		target.setWhsId(header.getToWhs());

 		target.setUnit(dtl.getUnit()); 		// 单位
 		target.setSkuId(dtl.getToSku()); 	// 物料ID
 		target.setOwner(dtl.getToOwner()); 	// 货主ID
 		target.setLotNo(dtl.getToLotno()); 	// 内部批次号
 		target.setFactory(dtl.getToFactory()); 	// 工厂
 		target.setInvAttr(dtl.getToInvAttr()); 	// 库存性质
 		target.setVendorId(dtl.getToVendor()); 	// 供应商ID
 		target.setQaStatus(dtl.getToQaStatus());// 品质状态

 		// 目的仓日志
 		InvTrans targetInvTrans = new InvTrans();
 		targetInvTrans.setOperator(loginName);
 		targetInvTrans.setCreateUser(loginName);
 		targetInvTrans.setCreateTime(localDate);
 		
 		targetInvTrans.setToUnit(dtl.getUnit()); // 单位
 		targetInvTrans.setToSkuId(dtl.getToSku());
 		targetInvTrans.setToOwner(dtl.getToOwner());
 		targetInvTrans.setDocLineNo(dtl.getTransferLineNo()); // 单据行号

 		targetInvTrans.setToWhsId(header.getToWhs());
 		targetInvTrans.setDocNo(header.getTransferNo());
 		targetInvTrans.setDocType(header.getTransferType());
 		targetInvTrans.setTransTime(header.getTransferCreateTime());

 		targetInvTrans.setOpCode(RETURN);
 		targetInvTrans.setStatus(InvTransStatusEnum.FINISHED.code);

 		targetInvTrans.setToPreInQty(target.getPreInQty()); // 预收数量
 		inventoryService.inventoryIn(target, targetInvTrans);
 		
 		// 变更产品SN状态
 		for (TransferDtlGoods transferDtlGood : dtlGoodsList) {
 			Goods goods = goodsService.selectByGoodsId(transferDtlGood.getGoodsId());
 			String oldGoodsJson = JSON.toJSONString(goods); // 原先的json

 			goods.setModifyUser(loginName);
 			goods.setModifyTime(localDate);
 			goods.setStatus(GoodsStatusEnum.WAIT_UP.code);
 			goodsService.updateGoods(null, goods);	 		// 更改SN状态为待上架
 			
 			goods.setPkgId(null);
 			goodsService.updateGoodsDePackage(goods);		// 清空SN的PKG_id
 			
 			String newGoodsJson = JSON.toJSONString(goods); // 更新后的json

 			// 生成SN操作日志
 			GoodsLog goodsLog = new GoodsLog();
 			goodsLog.setOpCode(RETURN);
 			goodsLog.setOperator(loginName);
 			goodsLog.setCreateUser(loginName);
 			goodsLog.setCreateTime(localDate);
 			goodsLog.setGoodsSn(transferDtlGood.getGoodsSn());

 			goodsLog.setUpdateContent("未更新的:" + oldGoodsJson + ",更新的:" + newGoodsJson);
 			goodsService.insertGoodsLog(goodsLog);
 		}
 	}
 	
 	
 	/**
     * 导出转仓单列表
     *
     * @param request
     * @param response
 	 * @throws Exception 
     * @throws Exception
     */
	public void export(SrarchTransferWareHouseRequest search, HttpServletRequest request,
					   HttpServletResponse response) throws Exception {
		//查询当前用户权限仓库
		List<Integer> whsIdList = warehouseService.getWareHouseIds(request);
//		List<Integer> whsIdList=Arrays.asList(1,2,3,4,5,6,7,8);

		ServletOutputStream out = null;
		XSSFWorkbook workbook = null;
		try {
			search.setWareHouseIds(whsIdList);
			if (search.getStartTime() != null) {
				search.setStartDate(DateUtils.getStartTime(search.getStartTime()));
			}
			if (search.getEndTime() != null) {
				search.setEndDate(DateUtils.getEndTime(search.getEndTime()));
			}

			List<TransferWareHouseExt> datas = transferHeaderMapper.getListTable(search);

			datas.forEach(one -> {
				if (one.getTransferType()!=null){
					TransferTypeEnum typeEnum = TransferTypeEnum.getEnumByCode(one.getTransferType());
					if (typeEnum!=null){
						one.setTransferTypeStr(typeEnum.getEnumName());
					}
				}
				one.setStatusDesc(transferHeaderStatusMap.get(one.getStatus()));
				one.setPrintFlagDesc(printFlagMap.get(one.getPrintFlag()));
			});

			List<ExcelExportConfig> configs = new ArrayList<>();
			configs.add(new ExcelExportConfig("转仓单号", "transferNo", 120));
			configs.add(new ExcelExportConfig("单据类型", "transferTypeStr", 120));
			configs.add(new ExcelExportConfig("转仓仓", "fmWhsName", 120));
			configs.add(new ExcelExportConfig("目的仓", "toWhsName", 120));
			configs.add(new ExcelExportConfig("车牌号", "deliveryVehicleNo", 120));
			configs.add(new ExcelExportConfig("司机名称", "driver", 120));
			configs.add(new ExcelExportConfig("转仓数量", "orderQty", 120));
			configs.add(new ExcelExportConfig("接收数量", "cmpQty", 300));
			configs.add(new ExcelExportConfig("转仓时间", "transferCreateTime", 120));
			configs.add(new ExcelExportConfig("接收时间", "transferCmpTime", 120));
			configs.add(new ExcelExportConfig("状态", "statusDesc", 120));
			configs.add(new ExcelExportConfig("转出仓仓管员", "fmBusinessMan", 120));
			configs.add(new ExcelExportConfig("转出仓管员名称", "fmBusinessManName", 120));
			configs.add(new ExcelExportConfig("目的仓管员", "toBusinessMan", 120));
			configs.add(new ExcelExportConfig("目的仓管员名称", "toBusinessManName", 120));
			configs.add(new ExcelExportConfig("单据打印", "printFlagDesc", 120));
			configs.add(new ExcelExportConfig("创建时间", "createTime", 120));
			configs.add(new ExcelExportConfig("创建人", "createUser", 120));
			configs.add(new ExcelExportConfig("修改时间", "modifyTime", 120));
			configs.add(new ExcelExportConfig("修改人", "modifyUser", 120));

			workbook = HttpExcel.newListToExcel(datas, configs);
			String userAgent = request.getHeader("USER-AGENT");
			String fileName = "库区库存";
			if (userAgent.contains("Mozilla")) {
				fileName = new String(fileName.getBytes(), "ISO8859-1");
			} else {
				fileName = URLEncoder.encode(fileName, "utf8");
			}
			response.setContentType("application/octet-stream");
			response.setHeader("Content-Disposition", "attachment;fileName=" + fileName + ".xlsx");
			response.flushBuffer();
			out = response.getOutputStream();
			workbook.write(out);
		} catch (Exception e) {
			e.printStackTrace();
			throw e;
		} finally {
			if (out != null) {
				out.flush();
				out.close();
			}
			if(workbook != null) {
				workbook.close();
			}
		}
	}
 	
 	
	/**
	 * 打印转仓单pdf
	 * 
	 * @param transferHeaderId
	 * @param servletRequest
	 * @param response
	 * @throws Exception
	 */
	/*@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public void print(Integer transferHeaderId, HttpServletRequest servletRequest, 
			HttpServletResponse response) throws Exception {
		InputStream inputStream = null;
		OutputStream outputStream = null;
		try {
			String loginName = HttpSessionUtil.getLoginName(servletRequest);
			
			// 库存调拨单表头
			TransferHeader transferHeader = transferHeaderMapper.selectById(transferHeaderId);
			transferHeader.setPrintFlag(PrintFlagEnum.YES.code);
			transferHeader.setModifyUser(loginName);
			transferHeader.setModifyTime(new Date());
			transferHeaderMapper.updateById(transferHeader);
			
			// 获取文件流
			ClassPathResource resource = new ClassPathResource(FileUrlString.TRANSFER_PRINT);
			inputStream = resource.getInputStream();
			JasperReport jasperReport = (JasperReport) JRLoader.loadObject(inputStream);
			
			// 优化性能
			DefaultJasperReportsContext context = DefaultJasperReportsContext.getInstance();
			JRPropertiesUtil.getInstance(context).setProperty("net.sf.jasperreports.xpath.executer.factory", 
					"net.sf.jasperreports.engine.util.xml.JaxenXPathExecuterFactory");
			
			// 入参
			Map<String, Object> parameters = new HashMap<>(1);
			parameters.put("TRANSFER_HEADER_ID", transferHeaderId);
			JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource.getConnection());
			
			// 设置pdf尺寸
			jasperPrint.setPageWidth(595);
			jasperPrint.setPageHeight(396);
			jasperPrint.setLeftMargin(0);
			jasperPrint.setRightMargin(0);
			jasperPrint.setTopMargin(0);
			jasperPrint.setBottomMargin(0);
			
			String pdfName = new String("转仓单".getBytes(), "iso8859-1") + ".pdf";
			
			response.setContentType("application/pdf");
//			response.setHeader("Content-Disposition", "inline;");
			response.setHeader("Content-Disposition", "attachment; filename=" + pdfName);
			outputStream = response.getOutputStream();
			JasperExportManager.exportReportToPdfStream(jasperPrint, outputStream);
		} catch (Exception e){
			e.printStackTrace();
			throw e;
		} finally {
			if(outputStream != null) {
				outputStream.close();
			}
			if(inputStream != null) {
				inputStream.close();
			}
		}
	}*/
	
    /**
	 * 打印转仓单pdf
	 *
	 * @param servletRequest
	 * @param response
	 * @throws Exception
	 */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public void print(List<Integer> transferHeaderIds, HttpServletRequest servletRequest, 
			HttpServletResponse response) throws Exception {
		InputStream inputStream = null;
		OutputStream outputStream = null;
		try {
			String loginName = HttpSessionUtil.getLoginName(servletRequest);
			
			// 库存调拨单表头
			transferHeaderMapper.updatePrintFlag(PrintFlagEnum.YES.code, loginName, transferHeaderIds);
			
			// 获取文件流
			ClassPathResource resource = new ClassPathResource(FileUrlString.TRANSFER_PRINT);
			inputStream = resource.getInputStream();
			JasperReport jasperReport = (JasperReport) JRLoader.loadObject(inputStream);
			
			// 入参
			Map<String, Object> parameters = new HashMap<>(1);
			List<ExporterInputItem> items = new ArrayList<ExporterInputItem>(transferHeaderIds.size());
			for (Integer transferHeaderId : transferHeaderIds) {
				parameters.clear();
				parameters.put("TRANSFER_HEADER_ID", transferHeaderId);
				JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource.getConnection());
				
				// 设置pdf尺寸
				jasperPrint.setPageWidth(595);
				jasperPrint.setPageHeight(396);
				jasperPrint.setLeftMargin(0);
				jasperPrint.setRightMargin(0);
				jasperPrint.setTopMargin(0);
				jasperPrint.setBottomMargin(0);
				items.add(new SimpleExporterInputItem(jasperPrint));
			}
			String pdfName = new String("转仓单".getBytes(), "iso8859-1") + ".xlsx";
			response.setContentType("application/xls");   
			response.setCharacterEncoding("UTF-8"); 
			response.setHeader("Content-Disposition", "attachment; filename=" + pdfName);
			outputStream = response.getOutputStream();
			
			// Xls格式的导出器 JRXlsAbstractExport
			JRXlsxExporter exporter = new JRXlsxExporter();
			
			//设置输入项   
			ExporterInput exporterInput = new SimpleExporterInput(items);
			exporter.setExporterInput(exporterInput);
			
			//设置输出项   
			OutputStreamExporterOutput exporterOutput = new SimpleOutputStreamExporterOutput(outputStream);   
			exporter.setExporterOutput(exporterOutput);
			// 导出
			exporter.exportReport();
		} catch (Exception e){
			e.printStackTrace();
			throw e;
		} finally {
			if(outputStream != null) {
				outputStream.close();
			}
			if(inputStream != null) {
				inputStream.close();
			}
		}
	}

	/**
	 * 打印转仓单pdf
	 * @param servletRequest
	 * @param response
	 * @throws Exception
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public Result printNew(List<Integer> transferHeaderIds, HttpServletRequest servletRequest,
					  HttpServletResponse response) throws Exception {
		InputStream inputStream = null;
		OutputStream outputStream = null;
		Connection connection = null;
		try {
			String loginName = HttpSessionUtil.getLoginName(servletRequest);

			// 库存调拨单表头
			transferHeaderMapper.updatePrintFlag(PrintFlagEnum.YES.code, loginName, transferHeaderIds);

			// 获取文件流
			ClassPathResource resource = new ClassPathResource(FileUrlString.TRANSFER_PRINT);
			inputStream = resource.getInputStream();
			JasperReport jasperReport = (JasperReport) JRLoader.loadObject(inputStream);

			// 入参
			Map<String, Object> parameters = new HashMap<>(1);
			List<ExporterInputItem> items = new ArrayList<ExporterInputItem>(transferHeaderIds.size());
			connection = dataSource.getConnection();
			for (Integer transferHeaderId : transferHeaderIds) {
				parameters.clear();

				parameters.put("TRANSFER_HEADER_ID", transferHeaderId);
				JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, connection);

				// 设置pdf尺寸
				jasperPrint.setPageWidth(595);
				jasperPrint.setPageHeight(396);
				jasperPrint.setLeftMargin(0);
				jasperPrint.setRightMargin(0);
				jasperPrint.setTopMargin(0);
				jasperPrint.setBottomMargin(0);
				items.add(new SimpleExporterInputItem(jasperPrint));
			}
			String absolutePath = fileService.saveFile(items, "转仓单", "xlsx");
			//返回对应的路径
			Result result = new Result();
			result.setData(absolutePath);

			return result;

		} catch (Exception e){
			e.printStackTrace();
			throw e;
		} finally {
			if(outputStream != null) {
				outputStream.close();
			}
			if(inputStream != null) {
				inputStream.close();
			}
			if(connection!=null){
				connection.close();
			}
		}
	}

	public void exportSNList(BigDecimal headerId, HttpServletRequest request,
					   HttpServletResponse response) throws Exception {
		//查询当前用户权限仓库
//		List<Integer> whsIdList = warehouseService.getWareHouseIds(request);
//		List<Integer> whsIdList=Arrays.asList(1,2,3,4,5,6,7,8);

		ServletOutputStream out = null;
		XSSFWorkbook workbook = null;
		try {


			List<TransferGoodsExt> datas = transferHeaderMapper.selectSnExt(headerId);

			datas.forEach(one -> {
				if (one.getStatus()!=null){
					TransferDtlGoodStatusEnum enumByCode = TransferDtlGoodStatusEnum.getEnumByCode(one.getStatus());
					if (enumByCode!=null){
						one.setStatusStr(enumByCode.getEnumName());
					}
				}
			});

			List<ExcelExportConfig> configs = new ArrayList<>();
			configs.add(new ExcelExportConfig("SN", "goodsSn", 120));
			configs.add(new ExcelExportConfig("状态", "statusStr", 120));
			workbook = HttpExcel.newListToExcel(datas, configs);
			String userAgent = request.getHeader("USER-AGENT");
			String fileName = "转仓SN";
			if (userAgent.contains("Mozilla")) {
				fileName = new String(fileName.getBytes(), "ISO8859-1");
			} else {
				fileName = URLEncoder.encode(fileName, "utf8");
			}
			response.setContentType("application/octet-stream");
			response.setHeader("Content-Disposition", "attachment;fileName=" + fileName + ".xlsx");
			response.flushBuffer();
			out = response.getOutputStream();
			workbook.write(out);
		} catch (Exception e) {
			e.printStackTrace();
			throw e;
		} finally {
			if (out != null) {
				out.flush();
				out.close();
			}
			if(workbook != null) {
				workbook.close();
			}
		}
	}


}
